﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using NUnit.Framework;

using LowLevelGraphics;

namespace UnitTests
{
    /// <summary>
    /// 
    /// </summary>
    [TestFixture]
    public class TestUnsafeBitmap
    {
        private UnsafeBitmap m_Bitmap = null;
        private int m_nCompletePixelCount = -1;
        private Bitmap m_DotnetBitmap = null;
        /// <summary>
        /// Sets up.
        /// </summary>
        [SetUp]
        public void SetUp()
        {
            m_Bitmap = new UnsafeBitmap(new Bitmap(100, 100));
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;
            Random random = new Random(this.GetHashCode() + DateTime.Now.Millisecond);

            m_nCompletePixelCount = nHeight * nWidth;

            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    m_Bitmap.SetPixel(x, y, Color.FromArgb(random.Next(255), random.Next(255), random.Next(255)));
                }
            }

            m_Bitmap.UnlockImage();
            m_DotnetBitmap = (Bitmap)m_Bitmap.InternalBitmap.Clone();
            m_Bitmap.LockImage();
        }

        /// <summary>
        /// Gets the pixels.
        /// </summary>
        [Test]
        public void GetPixels()
        {
            Color color = Color.Transparent;
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    Assert.AreEqual(m_Bitmap.GetPixel(x, y), m_Bitmap[x, y]);
                }
            }
        }

        [Test]
        public void TestGetPixel()
        {
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;

            //Test normal pixel access
            int nCount = 0;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    if (m_Bitmap.GetPixel(x, y) == m_DotnetBitmap.GetPixel(x, y))
                    {
                        nCount++;
                    }
                }
            }
            Assert.AreEqual(nHeight * nWidth, nCount);
        }

        [Test]
        public void TestIndexerSingleChannel()
        {
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;

            //Test normal pixel access
            int nCount = 0;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        if (m_Bitmap[x, y, i] == GetChannel(m_DotnetBitmap.GetPixel(x, y), i))
                        {
                            nCount++;
                        }
                    }
                }
            }

            //Multiplicate by 3 because we got 3 channels here...
            Assert.AreEqual(nHeight * nWidth * 3, nCount);
        }

        [Test]
        public void TestDefaultIndexer()
        {
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;

            //Test normal pixel access
            int nCount = 0;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    if (m_Bitmap[x, y] == m_DotnetBitmap.GetPixel(x, y))
                    {
                        nCount++;
                    }
                }
            }
            //Multiplicate by 3 because we got 3 channels here...
            Assert.AreEqual(nHeight * nWidth, nCount);
        }

        [Test]
        public void TestGrayIndexer()
        {
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;

            //Test normal pixel access
            int nCount = 0;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    if (m_Bitmap[x, y, true] == ColorFunctions.GrayColor(m_DotnetBitmap.GetPixel(x, y)))
                    {
                        nCount++;
                    }
                }
            }
            Assert.AreEqual(nHeight * nWidth, nCount);
        }

        [Test]
        public void TestGetPixelDirect()
        {
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;

            //Test normal pixel access
            int nCount = 0;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    byte r = 0;
                    byte g = 0;
                    byte b = 0;
                    byte a = 0;
                    m_Bitmap.GetPixelDirect(x, y, out a, out r, out g, out b);

                    //Test all possibilites and increase count +1 if all has been done correctly
                    Color colorDirect = m_Bitmap.GetPixelDirect(x, y);
                    Color colorByPoint = m_Bitmap.GetPixelDirect(new Point(x, y));
                    if (m_DotnetBitmap.GetPixel(x, y) == Color.FromArgb(a, r, g, b) && colorDirect == colorByPoint)
                    {
                        nCount++;
                    }
                }
            }
            Assert.AreEqual(nHeight * nWidth, nCount);
        }

        /// <summary>
        /// Gets the channel.
        /// </summary>
        /// <param name="_color">The _color.</param>
        /// <param name="_nChannel">The _n channel.</param>
        /// <returns></returns>
        private int GetChannel(Color _color, int _nChannel)
        {
            int[] aChannel = new int[4];
            aChannel[0] = _color.R;
            aChannel[1] = _color.G;
            aChannel[2] = _color.B;
            aChannel[3] = _color.A;
            return aChannel[_nChannel];
        }

        /// <summary>
        /// Tests the get pixel direct int.
        /// Attention: This is not the same as Color.ToArgb()
        /// </summary>
        [Test]
        public void TestGetPixelDirectInt()
        {
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;

            //Test normal pixel access
            int nCount = 0;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    int nColor = m_Bitmap.GetPixelDirectInt(x, y);

                    if (ColorFunctions.ToIntRGB(m_DotnetBitmap.GetPixel(x, y)) == nColor)
                    {
                        nCount++;
                    }
                }
            }
            Assert.AreEqual(nHeight * nWidth, nCount);
        }

        /// <summary>
        /// Tests the "get next pixel"-Routine.
        /// </summary>
        [Test]
        public void TestGetNextPixel()
        {
            int nPixelCount = m_DotnetBitmap.Width * m_DotnetBitmap.Height;
            int nCount = 0;

            Color[] aPixelCount = new Color[nPixelCount];

            int nIndex = 0;
            for (int y = 0; y < m_DotnetBitmap.Height; y++)
            {
                for (int x = 0; x < m_DotnetBitmap.Width; x++)
                {
                    aPixelCount[nIndex] = m_DotnetBitmap.GetPixel(x, y);
                }
            }

            //This fails. Sequence and error unknown until yet. 
            for (int i = 0; i < nPixelCount; i++)
            {
                Color color = m_Bitmap.GetNextPixel();
                if (color == aPixelCount[i])
                {
                    nCount++;
                }
            }
            Assert.AreEqual(nPixelCount, nCount);
        }

        /// <summary>
        /// Pixels the count.
        /// </summary>
        [Test]
        public void PixelCount()
        {
            Assert.AreEqual(m_DotnetBitmap.Width * m_DotnetBitmap.Height, m_Bitmap.PixelCount);
        }

        /// <summary>
        /// Tests the get channel r_ g_ B.
        /// </summary>
        [Test]
        public void TestGetChannelR_G_B()
        {
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;

            //Test normal pixel access
            int nCount = 0;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    if (
                        m_Bitmap.GetPixelR(x, y) == m_DotnetBitmap.GetPixel(x, y).R
                        && m_Bitmap.GetPixelG(x,y) == m_DotnetBitmap.GetPixel(x,y).G
                        && m_Bitmap.GetPixelB(x,y) == m_DotnetBitmap.GetPixel(x,y).B)
                    {
                        nCount++;
                    }
                }
            }
            Assert.AreEqual(nHeight * nWidth, nCount);
        }

        /// <summary>
        /// Gets the gray pixel and gray pixel value.
        /// </summary>
        [Test]
        public void GetGrayPixelAndGrayPixelValue()
        {
            int nHeight = m_Bitmap.Height;
            int nWidth = m_Bitmap.Width;

            //Test normal pixel access
            int nCount = 0;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    Color color = m_Bitmap.GetPixel(x, y);
                    int nGray = m_Bitmap.GetGrayPixelValue(x, y);

                    if (ColorFunctions.GrayColor(m_DotnetBitmap.GetPixel(x, y)) == ColorFunctions.GrayColor(color)
                        && nGray == ColorFunctions.Gray(m_DotnetBitmap.GetPixel(x, y)))
                    {
                        nCount++;
                    }
                }
            }
            Assert.AreEqual(nHeight * nWidth, nCount);
        }

        /// <summary>
        /// Gets the index of the pixels per.
        /// </summary>
        [Test]
        public void TestGetCoordinatesFromIndex()
        {
            int nHeight = m_DotnetBitmap.Height;
            int nWidth = m_DotnetBitmap.Width;
            int nIndex = 0;
            int nCount = 0;
            int nPixelCount = nHeight * nWidth;

            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    Point pt = m_Bitmap.GetCoordinatesFromIndex(nIndex);
                    nIndex++;
                    if (pt == new Point(x, y))
                    {
                        nCount++;
                    }
                }
            }
            Assert.AreEqual(nPixelCount, nCount);
        }

        [Test]
        public void TestGetIndexFromCoordinates()
        {
            int nHeight = m_DotnetBitmap.Height;
            int nWidth = m_DotnetBitmap.Width;
            int nIndex = 0;
            int nCount = 0;
            int nPixelCount = nHeight * nWidth;
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    if (nIndex == m_Bitmap.GetIndexFromCoordinates(x, y))
                    {
                        nCount++;
                    }
                    nIndex++;
                }
            }
            Assert.AreEqual(nPixelCount, nCount);
        }

        /// <summary>
        /// Tears down.
        /// </summary>
        [TearDown]
        public void TearDown()
        {
            m_Bitmap.Dispose();
            m_Bitmap.InternalBitmap.Dispose();
            m_Bitmap = null;
        }
    }
}
